#ifndef __PLATFORMAUDIORESOURCE_INCLUDED
#define __PLATFORMAUDIORESOURCE_INCLUDED

namespace Audio
{	
	class ILocker
	{
	public:
		virtual ~ILocker(){}
		virtual void Lock() = 0;
		virtual void Unlock() = 0;
	};


	class LocalLocker
	{
	public:
		LocalLocker(ILocker* l)
			:locker(l)
		{
			locker->Lock();
		}

		~LocalLocker()
		{
			locker->Unlock();
		}

	private:
		ILocker* locker;
	};

	class IRunable
	{
	public:
		virtual ~IRunable(){}
		virtual void Run() = 0;
		virtual UINT32 ReturnCode() = 0;
	};


	class IThread
	{
	public:		
		
		virtual ~IThread(){}	
		virtual void Start(IRunable* runable) = 0;
		virtual void Join() = 0;
		virtual void Stop() = 0;
		virtual BOOL HasStopRequest() = 0;
	
		
	};

	class IEvent
	{
	public:
		virtual ~IEvent(){};
		virtual void Signal() = 0;
		virtual void WaitOn() = 0;
	};

	class IVoice : public ErroableObject
	{
	public:
		virtual ~IVoice(){};

		virtual void Start() = 0;
		virtual void Stop() = 0;
		virtual void SubmitData(UINT8* raw, UINT32 size, SubmitBufferType bufferType) = 0;
		
		virtual void SetUserData(void* pv) = 0;
		virtual void* GetUserData() = 0;

		virtual float GetVolume() = 0;
		virtual void  SetVolume(FLOAT vol) = 0;

		virtual BOOL  IsPlaying() = 0;
		virtual UINT32 GetSamplePlayed() = 0;
	};
	
	
	class IAudioDeviceCallBack
	{
	public:
		virtual ~IAudioDeviceCallBack(){}
		virtual void OnNeedMoreData(void* context) = 0;		
		virtual void OnStreamEnd(void* context) = 0;
		virtual void OnVoiceError(void* context) = 0;
	};	
	


	class IAudioDevice : public ErroableObject
	{
	public:
		virtual ~IAudioDevice(){}
		virtual void Init() = 0;
		virtual void Destroy() = 0;

		virtual IVoice* CreateVoice(void* info, UINT32 infoSize) = 0;
		virtual void DestroyVoice(IVoice*& voice) = 0;

		virtual void SetDeviceCallback(IAudioDeviceCallBack* callback) = 0;
		virtual IAudioDeviceCallBack* GetDeviceCallback() = 0;

	};		
	

	class IFactory
	{
	public:
		
		virtual ~IFactory(){}
		virtual IAudioDevice* CreateAudioDevice() = 0;
		virtual void DestroyAudioDevice(IAudioDevice*& device) = 0;

		virtual ILocker* CreateLocker() = 0;
		virtual void DestroyLocker(ILocker*& locker) = 0;

		virtual IThread* CreateThread() = 0;
		virtual void DestroyThread(IThread*& t) = 0;

		virtual IEvent* CreateEventObject() = 0;
		virtual void DestroyEventObject(IEvent*& e) = 0;
	};

	
	class System
	{
	public:
		static void Init(IFactory* factory);
		static void Destroy();

		static IFactory* GetFactory(){ return factory;}

		static IAudioDevice* CreateAudioDevice(){ return factory->CreateAudioDevice(); }
		static void DestroyAudioDevice(IAudioDevice*& device){ return factory->DestroyAudioDevice(device); }

		static ILocker* CreateLocker() { return factory->CreateLocker();}
		static void DestroyLocker(ILocker*& locker){ return factory->DestroyLocker(locker);}

		static IThread* CreateThread(){ return factory->CreateThread();}
		static void DestroyThread(IThread*& t){ return factory->DestroyThread(t);}

		static IEvent* CreateEventObject(){ return factory->CreateEventObject();}
		static void DestroyEventObject(IEvent*& e){ return factory->DestroyEventObject(e);}
	private:
		static IFactory* factory;
	};

}

#endif
